//
//  SLCADirtyRectController.m
//  Objective-C
//
//  Created by S_Line on 2018/7/4.
//  Copyright © 2018年 S_Line. All rights reserved.
//

#import "SLCADirtyRectController.h"

#import "DrawingView.h"

#define WIDTH 10
#define HEIGHT 10
#define DEPTH 10
#define SIZE 100.0
#define SPACING 150.0
#define CAMERA_DISTANCE 500.0
#define PERSPECTIVE(z) (float)CAMERA_DISTANCE/(z + CAMERA_DISTANCE)

@interface SLCADirtyRectController ()<UIScrollViewDelegate>

@property (nonatomic, weak) UIScrollView *scrollView;
@property (nonatomic, strong) NSMutableSet *recyclePool;

@end

@implementation SLCADirtyRectController

- (void)initNavBar {
    self.navTitle = @"DirtyRect 脏矩形";
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self initNavBar];
    
    [self initView];
}

- (void)initView {
//    DrawingView *drawingView = [[DrawingView alloc] initWithFrame:CGRectMake(0, kNavigationBarHeight + 10, kScreenWidth, kScreenWidth)];
//    drawingView.backgroundColor = [UIColor whiteColor];
//    [self.view addSubview:drawingView];
    
    self.recyclePool = [NSMutableSet new];
    
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, kNavigationBarHeight, kScreenWidth, kScreenHeight - kNavigationBarHeight - kSafeBottomMargin)];
    scrollView.delegate = self;
    scrollView.backgroundColor = [UIColor blackColor];
    self.scrollView = scrollView;
    [self.view addSubview:scrollView];
    
    // set content size
    scrollView.contentSize = CGSizeMake((WIDTH - 1) * SPACING, (HEIGHT - 1) * SPACING);
    
    // set up perspective transform
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = - 1.0 / CAMERA_DISTANCE;
    self.scrollView.layer.sublayerTransform = transform;
    
//    // create layers
//    for (int i = DEPTH - 1; i >= 0; i--) {
//        for (int j = 0; j < HEIGHT; j++) {
//            for (int k = 0; k < WIDTH; k++) {
//                // create layer
//                CALayer *layer = [CALayer layer];
//                layer.frame = CGRectMake(0, 0, SIZE, SIZE);
//                layer.position = CGPointMake(k * SPACING, j * SPACING);
//                layer.zPosition = - SPACING * (float)i;
//                // set backgroundColor
//                layer.backgroundColor = [UIColor colorWithWhite:1.0 - (float)i * (1.0 / DEPTH) alpha:1].CGColor;
//                // attach to scrollview
//                [self.scrollView.layer addSublayer:layer];
//            }
//        }
//    }
//
//    SLog(@"displayed: %d", DEPTH * HEIGHT * WIDTH);
}

- (void)viewDidLayoutSubviews {
    [self updateLayers];
}

- (void)updateLayers {
    
    // calculate clipping bounds
    CGRect bounds = self.scrollView.bounds;
    bounds.origin = self.scrollView.contentOffset;
    bounds = CGRectInset(bounds, -SIZE / 2.0, -SIZE / 2.0);
    
    // add existing layers to pool
    [self.recyclePool addObjectsFromArray:self.scrollView.layer.sublayers];
    // disable animation
    [CATransaction begin];
    [CATransaction setDisableActions:true];
    
    // create layers
    NSUInteger recycled = 0;
    NSMutableArray *visibleLayers = [NSMutableArray new];
    for (int i = DEPTH - 1; i >= 0; i--) {
        // increase bounds size to compensate for perspective
        CGRect adjusted = bounds;
        adjusted.size.width /= PERSPECTIVE(i * SPACING);
        adjusted.size.height /= PERSPECTIVE(i * SPACING);
        adjusted.origin.x -= (adjusted.size.width - bounds.size.width) / 2.0;
        adjusted.origin.y -= (adjusted.size.height - bounds.size.height) / 2.0;
        for (int j = 0; j < HEIGHT; j++) {
            // check if vertically outside visible rect
            if (j * SPACING < adjusted.origin.y || j * SPACING >= adjusted.origin.y + adjusted.size.height) {
                continue;
            }
            for (int k = 0; k < WIDTH; k++) {
                if (k * SPACING < adjusted.origin.x || k * SPACING > adjusted.origin.x + adjusted.size.width) {
                    continue;
                }
                
                // create layer
                CALayer *layer = [self.recyclePool anyObject];
                if (layer) {
                    recycled ++;
                    [self.recyclePool removeObject:layer];
                } else {
                    layer = [CALayer layer];
                    layer.frame = CGRectMake(0, 0, SIZE, SIZE);
                }
                layer.position = CGPointMake(k * SPACING, j * SPACING);
                layer.zPosition = - SPACING * (float)i;
                // set backgroundColor
                layer.backgroundColor = [UIColor colorWithWhite:1.0 - (float)i * (1.0 / DEPTH) alpha:1].CGColor;
                // attach to scrollview
                [visibleLayers addObject:layer];
            }
        }
    }
    
    [CATransaction commit];
    // update layers
    self.scrollView.layer.sublayers = visibleLayers;
    
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self updateLayers];
}

@end
